
#include "main.h"
#include "adc.h"
#include "dac.h"
#include "display.h"
#include "eeprom.h"
#include "keybutton.h"
#include "led.h"
#include "uart.h"
#include <string.h>
#include <stdlib.h>


#define	DIGIT(s, no)	((s)[no] - '0')
const int _dyear = (1000*DIGIT(__DATE__, 7) + 100*DIGIT(__DATE__, 8) + 10*DIGIT(__DATE__, 9) + DIGIT(__DATE__, 10));
const int _dmonth = (__DATE__[2] == 'b' ? 2 : (__DATE__[2] == 'y' ? 5 : (__DATE__[2] == 'l' ? 7 : (__DATE__[2] == 'g' ? 8 :
	(__DATE__[2] == 'p' ? 9 : (__DATE__[2] == 't' ? 10 : (__DATE__[2] == 'v' ? 11 : (__DATE__[2] == 'c' ? 12 :
	(__DATE__[2] == 'n' ? (__DATE__[1] == 'a' ? 1 : 6) : (__DATE__[1] == 'a' ? 3 : 4))))))))));
const int _dday = ( 10 * (__DATE__[4] == ' ' ? 0 : DIGIT(__DATE__, 4)) + DIGIT(__DATE__, 5));
const int _thour = (10 * DIGIT(__TIME__, 0) + DIGIT(__TIME__, 1));
const int _tminute = (10 * DIGIT(__TIME__, 3) + DIGIT(__TIME__, 4));
const int _tsecond = (10 * DIGIT(__TIME__, 6) + DIGIT(__TIME__, 7));


vu32 gvSysTickCount = 0;
vu32 gvCurMode = MODE_UNKNOW;
VOUT_DATA gVout[VOUT_MAX] = {0,};

u32 gOldMode = MODE_UNKNOW;
u32 guSetKeepAlive = 0;
u32 guLastKeepAlive = 0;
VOUT_DATA gVoutTemp[VOUT_MAX] = {0,};

#define TRG_ON_mVOLT	250	// mV
#define STEP_DELAY		500	// mSec
static u32 _adc_ch = ADC_1, _adc_off[3] = {0,};
static u32 _adc_step = STEP_TOFF, _adc_temp = 0;

static void mainLoop(void);
static u32 fxUart1Parsing(u8 *pPktBuf, u32 pktCnt);
static u32 fxUart2Parsing(u8 *pPktBuf, u32 pktCnt);
static void dumpVout(VOUT_DATA Vout[VOUT_MAX]);
static void resetVoutData(void);


int main()
{
	/* Configure and enable the systick timer to generate an interrupt each 1 ms */
	SysTick_Config((SystemCoreClock / 1000));

	FLASH_Unlock();
	EE_Init();

	Uart_Init(fxUart1Parsing, fxUart2Parsing);
	Led_Init();
	Display_Init();
	Dac_Init();

	printf("!!! %s !!!\r\n", STR_TITLE);
	do {
		u32 lastTick;
		u16 versionInfo = 0;

		Dac_Set_Sel(DAC_1, 1);
		lastTick = gvSysTickCount + 10;
		while (lastTick > gvSysTickCount);
		Dac_Set_Sel(DAC_2, 1);
		lastTick = gvSysTickCount + 10;
		while (lastTick > gvSysTickCount);
		Dac_Set_Sel(DAC_3, 1);

		EE_ReadVariable(EEPROM_VERSION, &versionInfo);
		if (EEPROM_VERSION_INFO != versionInfo) {
			printf(" EEPROM_VERSION_INFO(%d) != %d\r\n", EEPROM_VERSION_INFO, versionInfo);
			EE_WriteVariable(EEPROM_VERSION, EEPROM_VERSION_INFO);

			resetVoutData();
		} else {
			for (u32 v=0; v<VOUT_MAX; v++) {
				DWORD *pVout = (DWORD *)&gVout[v];
				for (u32 i=0; i<VDATA_MAX; i++) {
					EE_ReadVariable32(EEPROM_VOUT1_TOFF_L +  v*100 + i*2, &pVout[i]);
				}
			}
		}

		lastTick = gvSysTickCount + 100;
		while (lastTick > gvSysTickCount);

		Dac_Set_Sel(DAC_1, 0);
		lastTick = gvSysTickCount + 10;
		while (lastTick > gvSysTickCount);
		Dac_Set_Sel(DAC_2, 0);
		lastTick = gvSysTickCount + 10;
		while (lastTick > gvSysTickCount);
		Dac_Set_Sel(DAC_3, 0);
	} while (0);
	Adc_Init();
	KeyButton_Init();

	dumpVout(gVout);

	gvCurMode = MODE_READY;
	mainLoop();
}


static void modeReady(u8 key, u32 first);
static void modeRemote(u8 key, u32 first);
static void modeRemoteVI2MD(u8 key, u32 first);
static void modeDacOut(u8 key, u32 first);
static void modeAdcIn(u8 key, u32 first);
extern void modeSetup(u8 key, u32 first);
extern void modeCalibration(u8 key, u32 first);
static MODE_CB cbModes[] = {
	{MODE_READY,		modeReady},
	{MODE_REMOTE,		modeRemote},
	{MODE_REMOTE_VI2MD,	modeRemoteVI2MD},
	{MODE_DACOUT,		modeDacOut},
	{MODE_ADCIN,		modeAdcIn},
	{MODE_SETUP,		modeSetup},
	{MODE_CALIBRATION,	modeCalibration},
};
void mainLoop()
{
	u32 modeChanged = 0;
	u8 key = 0;

	while (1) {
		if (gOldMode != gvCurMode) {
			modeChanged = 1;
			switch (gvCurMode) {
			case MODE_READY:
				printf("start MODE_READY\r\n");
				break;
			case MODE_REMOTE:
				printf("start MODE_REMOTE\r\n");
				break;
			case MODE_REMOTE_VI2MD:
				printf("start MODE_REMOTE_VI2MD\r\n");
				modeChanged = 2;
				break;
			case MODE_DACOUT:
				printf("start MODE_DACOUT\r\n");
				break;
			case MODE_ADCIN:
				printf("start MODE_ADCIN\r\n");
				break;
			case MODE_SETUP:
				printf("start MODE_SETUP\r\n");
				break;
			case MODE_CALIBRATION:
				printf("start MODE_CALIBRATION\r\n");
				break;
			}
			gOldMode = gvCurMode;

			if (1 == modeChanged) {
				Dac_Out_Host(NULL, 0);
				Dac_Set_Sel(DAC_3, 0);
				Adc_Stop();

				/* VI2MD Relay Off */
				Uart3_Send("+0001950000000000|REQ_PWROFF\r");
			}
		}

		Adc_Proc(gvCurMode, modeChanged);
		Dac_Proc(gvCurMode, modeChanged);
		Uart_Proc(gvCurMode, modeChanged);
		key = KeyButton_Proc();

		cbModes[gvCurMode].fx(key, modeChanged);
		modeChanged = 0;
	}
}
static void modeReady(u8 key, u32 first)
{
	static u8 _init = 0, _calibration = 0, _msg = 0;

	if (first) {
		LcdDrawRect(0, 0, LCD_SCREEN_WIDTH, LCD_SCREEN_HEIGHT, COLOR_BLACK);
		LcdLineString( 0, LCD_ALIGN_CENTER, STR_TITLE, COLOR_BLACK, COLOR_WHITE);
		LcdLineString(19, LCD_ALIGN_CENTER, "Mode : Standby", COLOR_BLACK, COLOR_WHITE);

		LcdLineString( 2, LCD_ALIGN_LEFT, "  [F1] DAC Out", COLOR_YELLOW, COLOR_BLACK);
		LcdLineString( 3, LCD_ALIGN_LEFT, "  [F2] ADC In", COLOR_YELLOW, COLOR_BLACK);
		LcdLineString( 4, LCD_ALIGN_LEFT, "  [F3] VDD Setup", COLOR_YELLOW, COLOR_BLACK);

		_init = 0;
		_calibration = 0;
		_msg = 0;
	}

	if (_msg && (guLastKeepAlive < gvSysTickCount)) {
		key = KEYBUTTON_BS;
	}

	switch (key) {
	case KEYBUTTON_0:
		_init++;
		if (5 < _init) {
			_init = 0;
			LcdLineString(11, LCD_ALIGN_CENTER, "VDDs Default Reset", COLOR_YELLOW, COLOR_BLACK);
			LcdLineString(12, LCD_ALIGN_CENTER, "[.]Save Cancel[BS]", COLOR_YELLOW, COLOR_BLACK);
			_msg = 1;
			guLastKeepAlive = gvSysTickCount + 5000;
		}
		break;
	case KEYBUTTON_2:
		_calibration++;
		if (5 < _calibration) {
			_calibration = 0;
			gvCurMode = MODE_CALIBRATION;
		}
		break;
	case KEYBUTTON_DOT:
	case KEYBUTTON_BS:
		if (_msg) {
			_msg = 0;
			LcdLineString(11, LCD_ALIGN_CENTER, "", COLOR_YELLOW, COLOR_BLACK);
			LcdLineString(12, LCD_ALIGN_CENTER, "", COLOR_YELLOW, COLOR_BLACK);
			LcdLineString(13, LCD_ALIGN_CENTER, "", COLOR_YELLOW, COLOR_BLACK);

			if (KEYBUTTON_DOT == key) {
				resetVoutData();
			}
		}
		break;
	case KEYBUTTON_OK:
		if (0 == _msg) {
			LcdLineString(11, LCD_ALIGN_RIGHT, "Build Date ", COLOR_YELLOW, COLOR_BLACK);
			sprintf(gszLine, "%04d-%02d-%02d ", _dyear, _dmonth, _dday);
			LcdLineString(12, LCD_ALIGN_RIGHT, gszLine, COLOR_YELLOW, COLOR_BLACK);
			sprintf(gszLine, "%02d:%02d:%02d ", _thour, _tminute, _tsecond);
			LcdLineString(13, LCD_ALIGN_RIGHT, gszLine, COLOR_YELLOW, COLOR_BLACK);
			_msg = 1;
			guLastKeepAlive = gvSysTickCount + 5000;
		} else {
			guLastKeepAlive = gvSysTickCount;
		}
		break;

	case KEYBUTTON_F1:
		gvCurMode = MODE_DACOUT;
		break;
	case KEYBUTTON_F2:
		gvCurMode = MODE_ADCIN;
		break;
	case KEYBUTTON_F3:
		gvCurMode = MODE_SETUP;
		break;

	default:
		if (KEYBUTTON_NONE != key) {
			_init = 0;
			_calibration = 0;
		}
		break;
	}
}
static void modeRemote(u8 key, u32 first)
{
	if (first) {
		LcdDrawRect(0, 0, LCD_SCREEN_WIDTH, LCD_SCREEN_HEIGHT, COLOR_BLACK);
		LcdLineString( 0, LCD_ALIGN_CENTER, STR_TITLE, COLOR_BLACK, COLOR_WHITE);
		if (MODE_REMOTE == gvCurMode) {
			LcdLineString(19, LCD_ALIGN_CENTER, "Mode : Remote", COLOR_BLACK, COLOR_WHITE);
		} else {
			LcdLineString(19, LCD_ALIGN_CENTER, "Mode : Remote ADCIN", COLOR_BLACK, COLOR_WHITE);
		}

		guLastKeepAlive = gvSysTickCount + 60*1000;
	}

	if (guLastKeepAlive < gvSysTickCount) {
		gvCurMode = MODE_READY;
	}
}
static void modeRemoteVI2MD(u8 key, u32 first)
{
	if (first) {
		/*LcdDrawRect(0, 0, LCD_SCREEN_WIDTH, LCD_SCREEN_HEIGHT, COLOR_BLACK);
		LcdLineString( 0, LCD_ALIGN_CENTER, STR_TITLE, COLOR_BLACK, COLOR_WHITE);
		LcdLineString(19, LCD_ALIGN_CENTER, "Mode : Remote VI2MD", COLOR_BLACK, COLOR_WHITE);

		LcdLineString( 2, LCD_ALIGN_LEFT, "  [F1] Exit", COLOR_YELLOW, COLOR_BLACK);*/
	}

	switch (_adc_step) {
	case STEP_TOFF:
		_adc_temp = Adc_Get_mV(_adc_ch);
		if (TRG_ON_mVOLT < _adc_temp) {
			_adc_step = STEP_TR;
			_adc_temp = (Dac_Out_Trigger(1) / 1000) + STEP_DELAY + gvSysTickCount;
		}
		break;
	case STEP_TR:
		if (_adc_temp < gvSysTickCount) {
			_adc_step = STEP_TON;
		}
		break;
	case STEP_TON:
		_adc_temp = Adc_Get_mV(_adc_ch);
		if (_adc_off[_adc_ch] > _adc_temp) {
			_adc_step = STEP_TF;
			_adc_temp = (Dac_Out_Trigger(0) / 1000) + STEP_DELAY + gvSysTickCount;
		}
		break;
	case STEP_TF:
		if (_adc_temp < gvSysTickCount) {
			_adc_step = STEP_TOFF;
		}
		break;
	}
	/*_adc_ch++;
	if (ADC_MAX <= _adc_ch) {
		_adc_ch = ADC_1;
	}*/

	switch (key) {
	case KEYBUTTON_F1:
		gvCurMode = MODE_READY;
		break;
	}
}
static void modeDacOut(u8 key, u32 first)
{
	if (first) {
		LcdDrawRect(0, 0, LCD_SCREEN_WIDTH, LCD_SCREEN_HEIGHT, COLOR_BLACK);
		LcdLineString( 0, LCD_ALIGN_CENTER, STR_TITLE, COLOR_BLACK, COLOR_WHITE);
		LcdLineString(19, LCD_ALIGN_CENTER, "Mode : DAC Out", COLOR_BLACK, COLOR_WHITE);

		LcdLineString( 2, LCD_ALIGN_LEFT, "  [F1] Exit", COLOR_YELLOW, COLOR_BLACK);

		LcdLineString( 4, LCD_ALIGN_RIGHT, "Toff,Ton[mS]", COLOR_LIME, COLOR_BLACK);
		LcdLineString( 5, LCD_ALIGN_RIGHT, "Tr,Tf[uS] Vr[mV]", COLOR_LIME, COLOR_BLACK);
		LcdLineString( 6, LCD_ALIGN_RIGHT, "VDD1 VDD2 VDD3", COLOR_RED, COLOR_BLACK);

		sprintf(gszLine, "Toff:%5d%5d%5d", gVout[VOUT_1].dwToff, gVout[VOUT_2].dwToff, gVout[VOUT_3].dwToff);
		LcdLineString( 7, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
		sprintf(gszLine, " Tr1:%5d%5d%5d", gVout[VOUT_1].dwTr1, gVout[VOUT_2].dwTr1, gVout[VOUT_3].dwTr1);
		LcdLineString( 8, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
		sprintf(gszLine, " Vr1:%5d%5d%5d", gVout[VOUT_1].dwVr1, gVout[VOUT_2].dwVr1, gVout[VOUT_3].dwVr1);
		LcdLineString( 9, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
		sprintf(gszLine, " Tr2:%5d%5d%5d", gVout[VOUT_1].dwTr2, gVout[VOUT_2].dwTr2, gVout[VOUT_3].dwTr2);
		LcdLineString(10, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
		sprintf(gszLine, " Vr2:%5d%5d%5d", gVout[VOUT_1].dwVr2, gVout[VOUT_2].dwVr2, gVout[VOUT_3].dwVr2);
		LcdLineString(11, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
		sprintf(gszLine, " Tr3:%5d%5d%5d", gVout[VOUT_1].dwTr3, gVout[VOUT_2].dwTr3, gVout[VOUT_3].dwTr3);
		LcdLineString(12, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
		sprintf(gszLine, " Vr3:%5d%5d%5d", gVout[VOUT_1].dwVr3, gVout[VOUT_2].dwVr3, gVout[VOUT_3].dwVr3);
		LcdLineString(13, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
		sprintf(gszLine, " Tr4:%5d%5d%5d", gVout[VOUT_1].dwTr4, gVout[VOUT_2].dwTr4, gVout[VOUT_3].dwTr4);
		LcdLineString(14, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
		sprintf(gszLine, " Vr4:%5d%5d%5d", gVout[VOUT_1].dwVr4, gVout[VOUT_2].dwVr4, gVout[VOUT_3].dwVr4);
		LcdLineString(15, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
		sprintf(gszLine, " Ton:%5d%5d%5d", gVout[VOUT_1].dwTon, gVout[VOUT_2].dwTon, gVout[VOUT_3].dwTon);
		LcdLineString(16, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
		sprintf(gszLine, " Tf1:%5d%5d%5d", gVout[VOUT_1].dwTf1, gVout[VOUT_2].dwTf1, gVout[VOUT_3].dwTf1);
		LcdLineString(17, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);

		//Adc_Start();
		Dac_Set_Sel(DAC_3, 1);
		Dac_Out_Host(gVout, 1);
	}

	switch (key) {
	case KEYBUTTON_F1:
		gvCurMode = MODE_READY;
		break;
	}
}
static void modeAdcIn(u8 key, u32 first)
{
	if (first) {
		LcdDrawRect(0, 0, LCD_SCREEN_WIDTH, LCD_SCREEN_HEIGHT, COLOR_BLACK);
		LcdLineString( 0, LCD_ALIGN_CENTER, STR_TITLE, COLOR_BLACK, COLOR_WHITE);
		LcdLineString(19, LCD_ALIGN_CENTER, "Mode : ADC In", COLOR_BLACK, COLOR_WHITE);
		
		LcdLineString( 2, LCD_ALIGN_LEFT, "  [F2] Exit", COLOR_YELLOW, COLOR_BLACK);

		LcdLineString( 4, LCD_ALIGN_RIGHT, "Tr,Tf[uS] Vr[mV]", COLOR_LIME, COLOR_BLACK);
		LcdLineString( 5, LCD_ALIGN_RIGHT, "VDD1 VDD2 VDD3", COLOR_YELLOW, COLOR_BLACK);

		sprintf(gszLine, " Tr1:%5d%5d%5d", gVout[VOUT_1].dwTr1, gVout[VOUT_2].dwTr1, gVout[VOUT_3].dwTr1);
		LcdLineString( 6, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
		sprintf(gszLine, " Vr1:%5d%5d%5d", gVout[VOUT_1].dwVr1, gVout[VOUT_2].dwVr1, gVout[VOUT_3].dwVr1);
		LcdLineString( 7, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
		sprintf(gszLine, " Tr2:%5d%5d%5d", gVout[VOUT_1].dwTr2, gVout[VOUT_2].dwTr2, gVout[VOUT_3].dwTr2);
		LcdLineString( 8, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
		sprintf(gszLine, " Vr2:%5d%5d%5d", gVout[VOUT_1].dwVr2, gVout[VOUT_2].dwVr2, gVout[VOUT_3].dwVr2);
		LcdLineString( 9, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
		sprintf(gszLine, " Tr3:%5d%5d%5d", gVout[VOUT_1].dwTr3, gVout[VOUT_2].dwTr3, gVout[VOUT_3].dwTr3);
		LcdLineString(10, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
		sprintf(gszLine, " Vr3:%5d%5d%5d", gVout[VOUT_1].dwVr3, gVout[VOUT_2].dwVr3, gVout[VOUT_3].dwVr3);
		LcdLineString(11, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
		sprintf(gszLine, " Tr4:%5d%5d%5d", gVout[VOUT_1].dwTr4, gVout[VOUT_2].dwTr4, gVout[VOUT_3].dwTr4);
		LcdLineString(12, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
		sprintf(gszLine, " Vr4:%5d%5d%5d", gVout[VOUT_1].dwVr4, gVout[VOUT_2].dwVr4, gVout[VOUT_3].dwVr4);
		LcdLineString(13, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
		sprintf(gszLine, " Tf1:%5d%5d%5d", gVout[VOUT_1].dwTf1, gVout[VOUT_2].dwTf1, gVout[VOUT_3].dwTf1);
		LcdLineString(14, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);

		LcdLineString(16, LCD_ALIGN_RIGHT, "ADC[mV]", COLOR_LIME, COLOR_BLACK);

		for (u32 i=0; i<ADC_MAX; i++) {
			u32 dwTrs[4] = {gVout[i].dwTr1, gVout[i].dwTr2, gVout[i].dwTr3, gVout[i].dwTr4};
			u32 dwVrs[4] = {gVout[i].dwVr1, gVout[i].dwVr2, gVout[i].dwVr3, gVout[i].dwVr4};
			u32 max = 0;

			for (u32 s=0; s<4; s++) {
				if (0 == dwTrs[s]) {
					break;
				}
				max = dwVrs[s];
			}
			if (max) {
				_adc_off[i] = (u32)(max * 0.85);
			} else {
				_adc_off[i] = 2000;
			}
		}

		_adc_ch = ADC_1;
		_adc_step = STEP_TOFF;
		_adc_temp = 0;

		Adc_Start();
		Dac_Set_Sel(DAC_3, 1);
		Dac_Out_Host(gVout, 0);
	}

	switch (_adc_step) {
	case STEP_TOFF:
		_adc_temp = Adc_Get_mV(_adc_ch);
		if (TRG_ON_mVOLT < _adc_temp) {
			_adc_step = STEP_TR;
			_adc_temp = (Dac_Out_Trigger(1) / 1000) + STEP_DELAY + gvSysTickCount;
		}
		break;
	case STEP_TR:
		if (_adc_temp < gvSysTickCount) {
			_adc_step = STEP_TON;
		}
		break;
	case STEP_TON:
		_adc_temp = Adc_Get_mV(_adc_ch);
		if (_adc_off[_adc_ch] > _adc_temp) {
			_adc_step = STEP_TF;
			_adc_temp = (Dac_Out_Trigger(0) / 1000) + STEP_DELAY + gvSysTickCount;
		}
		break;
	case STEP_TF:
		if (_adc_temp < gvSysTickCount) {
			_adc_step = STEP_TOFF;
		}
		break;
	}
	/*_adc_ch++;
	if (ADC_MAX <= _adc_ch) {
		_adc_ch = ADC_1;
	}*/

	switch (key) {
	case KEYBUTTON_F2:
		gvCurMode = MODE_READY;
		break;
	}
}


static u32 helpCmdLine(int argc);
static u32 ledCmdLine(int argc);
static u32 adcCmdLine(int argc);
static u32 relayCmdLine(int argc);
static u32 filterCmdLine(int argc);
static u32 hostCmdLine(int argc);

static u32 hostConnect(int argc);
static u32 hostDisconnect(int argc);
static u32 hostKeepalive(int argc);
static u32 hostStart(int argc);
static u32 hostStop(int argc);
static u32 hostGetData(int argc);
static u32 hostSetData(int argc);

static CMDLINE_CB cbCmdLines[] = {
	{"help",	4,	helpCmdLine},
	{"led", 	3,	ledCmdLine},
	{"adc", 	3,	adcCmdLine},
	{"relay",	5,	relayCmdLine},
	{"filter",	6,	filterCmdLine},
	{"host",	4,	hostCmdLine},
};
char gArgV[50][12] = {0,};
static u32 fxUart1Parsing(u8 *pPktBuf, u32 pktCnt)
{
	for (u32 i=0, j=0; i<_countof(cbCmdLines); i++) {
		if (0 == strncmp((const char *)pPktBuf, cbCmdLines[i].cmd, cbCmdLines[i].cmdLength)) {
			char *ptr = strtok((char *)pPktBuf, " ");

			memset(gArgV, 0, sizeof(gArgV));
			strcpy(gArgV[j++], ptr);
			while (ptr = strtok(NULL, " ")) {
				strcpy(gArgV[j++], ptr);
			}

			return cbCmdLines[i].fx(j);
		}
	}

	printf("Unknown command : %s\r\n", gArgV[1]);

	return (u32)-1;
}
static u32 helpCmdLine(int argc)
{
	for (u32 i=1; i<_countof(cbCmdLines); i++) {
		cbCmdLines[i].fx(1);
	}

	return 0;
}
static u32 ledCmdLine(int argc)
{
	if (2 > argc) {
		printf("led [channel : 0~1] [onoff : 0~1]\r\n");
		printf("  ex) led 0 1\r\n");
	} else if (3 > argc) {
		u32 led = atoi(gArgV[1]);
		printf("led %d = %d\r\n", led, Led_Get(led));
	} else {
		u32 led = atoi(gArgV[1]);
		u32 on = atoi(gArgV[2]);
		Led_Set(led, on);
	}

	return 0;
}
static u32 adcCmdLine(int argc)
{
	if (2 > argc) {
		printf("adc [channel : 0~2]\r\n");
		printf("  ex) adc 0\r\n");
	} else {
		u32 adc = atoi(gArgV[1]);
		printf("adc %d = %d\r\n", adc, Adc_Get(adc));
	}

	return 0;
}
static u32 relayCmdLine(int argc)
{
	if (2 > argc) {
		printf("relay [channel : 0~2] [onoff : 0~1]\r\n");
		printf("  ex) relay 0 1\r\n");
	} else if (3 > argc) {
		u32 relay = atoi(gArgV[1]);
		printf("relay %d = %d\r\n", relay, Dac_Get_Sel(relay));
	} else {
		u32 relay = atoi(gArgV[1]);
		Dac_Set_Sel(relay, atoi(gArgV[2]));
	}

	return 0;
}
static u32 filterCmdLine(int argc)
{
	if (3 > argc) {
		printf("filter [channel : 0~1] [onoff : 0~1]\r\n");
		printf("  ex) led 0 1\r\n");
	} else if (3 > argc) {
		u32 filter = atoi(gArgV[1]);
		printf("filter %d = %d\r\n", filter, Dac_Get_Flt(filter));
	} else {
		u32 filter = atoi(gArgV[1]);
		Dac_Set_Flt(filter, atoi(gArgV[2]));
	}

	return 0;
}
static u32 hostCmdLine(int argc)
{
	//	2 : host connect
	//	2 : host disconnect
	//	2 : host keepalive
	// 42 : host start ...
	//	2 : host stop
	//  2 : host getdata
	// 42 : host setdata ...
	static CMDLINE_CB hostCmdLines[] = {
		{"connect",		7,	hostConnect},
		{"disconnect",	10,	hostDisconnect},
		{"keepalive", 	9,	hostKeepalive},
		{"start",		5,	hostStart},
		{"stop",		4,	hostStop},
		{"getdata", 	7,	hostGetData},
		{"setdata", 	7,	hostSetData},
	};

	for (u32 i=0; i<_countof(hostCmdLines); i++) {
		if (0 == strncmp((const char *)gArgV[1], hostCmdLines[i].cmd, hostCmdLines[i].cmdLength)) {
			return hostCmdLines[i].fx(argc);
		}
	}

	printf("Unknown host command : %s\r\n", gArgV[1]);

	return (u32)-1;
}

static u32 hostConnect(int argc)
{
	if (3 == argc) {
		guSetKeepAlive = atoi(gArgV[2])*1000 + 2000;
	}
	guLastKeepAlive = gvSysTickCount + guSetKeepAlive;
	gvCurMode = MODE_REMOTE;

	return 0;
}
static u32 hostDisconnect(int argc)
{
	gvCurMode = MODE_READY;
	Dac_Out_Host(NULL, 0);

	return 0;
}
static u32 hostKeepalive(int argc)
{
	guLastKeepAlive = gvSysTickCount + guSetKeepAlive;

	return 0;
}
static u32 hostStart(int argc)
{
	// host(0), save(1), vout1(2~14), vout2(15~27), vout3(28~40)
	if ((1+1+3*VDATA_MAX) > argc) {
		return -1;
	}

	for (u32 v=VOUT_1, idx=2; v<VOUT_MAX; v++) {
		DWORD *pVout = (DWORD *)&gVoutTemp[v];
		for (u32 i=0; i<VDATA_MAX; i++) {
			pVout[i] = atoi(gArgV[idx++]);
		}
	}
	//dumpVout(gVoutTemp);

	Dac_Set_Sel(DAC_3, 1);
	Dac_Out_Host(gVoutTemp, 1);

	return 0;
}
static u32 hostStop(int argc)
{
	gvCurMode = MODE_REMOTE;
	Dac_Out_Host(NULL, 0);
	Dac_Set_Sel(DAC_3, 0);
	Adc_Stop();

	return 0;
}
static u32 hostGetData(int argc)
{
	printf("host getdata");
	for (u32 v=VOUT_1; v<VOUT_MAX; v++) {
		DWORD *pVout = (DWORD *)&gVout[v];
		for (u32 i=0; i<VDATA_MAX; i++) {
			printf(" %d", pVout[i]);
		}
	}
	printf("\r\n");

	return 0;
}
static u32 hostSetData(int argc)
{
	// host(0), save(1), vout1(2~14), vout2(15~27), vout3(28~40)
	if ((1+1+3*VDATA_MAX) > argc) {
		return -1;
	}

	for (u32 v=VOUT_1, idx=2; v<VOUT_MAX; v++) {
		DWORD *pVout = (DWORD *)&gVout[v];
		for (u32 i=0; i<VDATA_MAX; i++) {
			pVout[i] = atoi(gArgV[idx++]);
			EE_WriteVariable32(EEPROM_VOUT1_TOFF_L + i*2, pVout[i]);
		}
	}
	dumpVout(gVout);

	return 0;
}

static void dumpVout(VOUT_DATA Vout[VOUT_MAX])
{
#if	1
	for (u32 i=VOUT_1; i<VOUT_MAX; i++) {
		printf("VOUT_%d\r\n", i+1);
		printf(" TOFF [mS]: %d\r\n", Vout[i].dwToff);
		printf(" TR1  [uS]: %d\r\n", Vout[i].dwTr1);
		printf(" VR1  [mV]: %d\r\n", Vout[i].dwVr1);
		printf(" TR2  [uS]: %d\r\n", Vout[i].dwTr2);
		printf(" VR2  [mV]: %d\r\n", Vout[i].dwVr2);
		printf(" TR3  [uS]: %d\r\n", Vout[i].dwTr3);
		printf(" VR3  [mV]: %d\r\n", Vout[i].dwVr3);
		printf(" TR4  [uS]: %d\r\n", Vout[i].dwTr4);
		printf(" VR4  [mV]: %d\r\n", Vout[i].dwVr4);
		printf(" TON  [mS]: %d\r\n", Vout[i].dwTon);
		printf(" TF1  [uS]: %d\r\n", Vout[i].dwTf1);
		printf(" OFFSET   : %d\r\n", Vout[i].dwOffset);
		printf(" RESERVED : %d\r\n", Vout[i].dwReserved);
	}
#endif
}

static void resetVoutData(void)
{
	gVout[VOUT_1].dwToff = 1;
	gVout[VOUT_1].dwTr1 = 1;
	gVout[VOUT_1].dwVr1 = 500;
	gVout[VOUT_1].dwTr2 = 1;
	gVout[VOUT_1].dwVr2 = 1000;
	gVout[VOUT_1].dwTr3 = 1;
	gVout[VOUT_1].dwVr3 = 1500;
	gVout[VOUT_1].dwTr4 = 1;
	gVout[VOUT_1].dwVr4 = 1800;
	gVout[VOUT_1].dwTon = 1;
	gVout[VOUT_1].dwTf1 = 1;
	gVout[VOUT_1].dwOffset = 0;
	gVout[VOUT_1].dwReserved = 0;

	gVout[VOUT_2].dwToff = 1;
	gVout[VOUT_2].dwTr1 = 1;
	gVout[VOUT_2].dwVr1 = 300;
	gVout[VOUT_2].dwTr2 = 1;
	gVout[VOUT_2].dwVr2 = 600;
	gVout[VOUT_2].dwTr3 = 1;
	gVout[VOUT_2].dwVr3 = 900;
	gVout[VOUT_2].dwTr4 = 1;
	gVout[VOUT_2].dwVr4 = 1200;
	gVout[VOUT_2].dwTon = 1;
	gVout[VOUT_2].dwTf1 = 1;
	gVout[VOUT_2].dwOffset = 0;
	gVout[VOUT_2].dwReserved = 0;

	gVout[VOUT_3].dwToff = 1;
	gVout[VOUT_3].dwTr1 = 1;
	gVout[VOUT_3].dwVr1 = 150;
	gVout[VOUT_3].dwTr2 = 1;
	gVout[VOUT_3].dwVr2 = 300;
	gVout[VOUT_3].dwTr3 = 1;
	gVout[VOUT_3].dwVr3 = 450;
	gVout[VOUT_3].dwTr4 = 1;
	gVout[VOUT_3].dwVr4 = 600;
	gVout[VOUT_3].dwTon = 1;
	gVout[VOUT_3].dwTf1 = 1;
	gVout[VOUT_3].dwOffset = 0;
	gVout[VOUT_3].dwReserved = 0;

	for (u32 v=0; v<VOUT_MAX; v++) {
		DWORD *pVout = (DWORD *)&gVout[v];
		for (u32 i=0; i<VDATA_MAX; i++) {
			EE_WriteVariable32(EEPROM_VOUT1_TOFF_L +  v*100 + i*2, pVout[i]);
		}
	}
}


static u32 fxUart2Parsing(u8 *pPktBuf, u32 pktCnt)
{
	#define RCV_MSG_REQ_PWRON	"REQ_PWRON"
	static u32 _modeCount = 0;

	//printf("+pPktBuf(%d) : %s\n", gvSysTickCount, pPktBuf);
	if (strstr((const char *)pPktBuf, RCV_MSG_REQ_PWRON)) {
		if (MODE_READY == gvCurMode) {
			gvCurMode = MODE_REMOTE_VI2MD;
			_modeCount = 0;

			Adc_Start();
			Dac_Set_Sel(DAC_3, 1);

			LcdDrawRect(0, 0, LCD_SCREEN_WIDTH, LCD_SCREEN_HEIGHT, COLOR_BLACK);
			LcdLineString( 0, LCD_ALIGN_CENTER, STR_TITLE, COLOR_BLACK, COLOR_WHITE);
			LcdLineString(19, LCD_ALIGN_CENTER, "Mode : Remote VI2MD", COLOR_BLACK, COLOR_WHITE);

			LcdLineString( 2, LCD_ALIGN_LEFT, "  [F1] Exit", COLOR_YELLOW, COLOR_BLACK);

			LcdLineString(16, LCD_ALIGN_RIGHT, "ADC[mV]", COLOR_LIME, COLOR_BLACK);
		}
		
		if (MODE_REMOTE_VI2MD == gvCurMode) {
			sprintf(gszLine, " Mode Count : %d", ++_modeCount);
			LcdLineString( 4, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);

			char *ptr1 = strrchr((const char *)pPktBuf, '[');
			char *ptr2 = strrchr((const char *)pPktBuf, ']');
			if ((ptr1 && ptr2) && (ptr1 < ptr2)) {
				u32 step = 0, count = 0, slope = 0;
				char *ptr3 = ptr1 + 1;

				step = atoi(ptr3);
				while (',' != *ptr3++) ;
				count = atoi(ptr3);
				slope = (step * count);
				//printf("step(%d) count(%d) slope(%d) %d\r\n", step, count, slope, gvSysTickCount);

				*ptr1++ = CHAR_CR;
				*ptr1++ = 0;
				pktCnt = ((u8 *)ptr1 - pPktBuf + 1);

				for (u32 i=0; i<ADC_MAX; i++) {
					u32 dwTrs[4] = {gVout[i].dwTr1, gVout[i].dwTr2, gVout[i].dwTr3, gVout[i].dwTr4};
					u32 dwVrs[4] = {gVout[i].dwVr1, gVout[i].dwVr2, gVout[i].dwVr3, gVout[i].dwVr4};
					u32 max = 0;

					for (u32 s=0; s<4; s++) {
						if (0 == dwTrs[s]) {
							break;
						}
						max = dwVrs[s];
					}
					if (max) {
						_adc_off[i] = (u32)(max * 0.85);
					} else {
						_adc_off[i] = 2000;
					}
					//printf("Vdd%d : slope(%duS) volt(%dmV) %d\r\n", i+1, slope, max, gvSysTickCount);

					gVoutTemp[i].dwToff = 1;	// minimum value...
					if (0 == slope) {
						gVoutTemp[i].dwTr1 = 1;	// minimum value...
					} else {
						gVoutTemp[i].dwTr1 = slope;
					}
					gVoutTemp[i].dwVr1 = max;
					gVoutTemp[i].dwTr2 = 0;
					gVoutTemp[i].dwVr2 = max;
					gVoutTemp[i].dwTr3 = 0;
					gVoutTemp[i].dwVr3 = max;
					gVoutTemp[i].dwTr4 = 0;
					gVoutTemp[i].dwVr4 = max;
					gVoutTemp[i].dwTon = 1;		// minimum value...
					gVoutTemp[i].dwTf1 = 1;		// minimum value...
				}
				Dac_Out_Host(gVoutTemp, 0);

				LcdLineString( 6, LCD_ALIGN_LEFT, "", COLOR_YELLOW, COLOR_BLACK);
				LcdLineString( 7, LCD_ALIGN_LEFT, "", COLOR_YELLOW, COLOR_BLACK);
				sprintf(gszLine, " Step Count : %d", count);
				LcdLineString( 8, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
				sprintf(gszLine, "   Step[uS] : %d", step);
				LcdLineString( 9, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
				sprintf(gszLine, "  Slope[uS] : %d", slope);
				LcdLineString(10, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
				LcdLineString(11, LCD_ALIGN_LEFT, "", COLOR_YELLOW, COLOR_BLACK);
				LcdLineString(12, LCD_ALIGN_LEFT, "", COLOR_YELLOW, COLOR_BLACK);
				LcdLineString(13, LCD_ALIGN_RIGHT, "VDD[mV]", COLOR_LIME, COLOR_BLACK);
				sprintf(gszLine, " VDD:%5d%5d%5d", gVoutTemp[VOUT_1].dwVr1, gVoutTemp[VOUT_2].dwVr1, gVoutTemp[VOUT_3].dwVr1);
				LcdLineString(14, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
			} else {
				pPktBuf[pktCnt++] = CHAR_CR;

				Dac_Out_Host(gVout, 0);

				sprintf(gszLine, " Tr1:%5d%5d%5d", gVout[VOUT_1].dwTr1, gVout[VOUT_2].dwTr1, gVout[VOUT_3].dwTr1);
				LcdLineString( 6, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
				sprintf(gszLine, " Vr1:%5d%5d%5d", gVout[VOUT_1].dwVr1, gVout[VOUT_2].dwVr1, gVout[VOUT_3].dwVr1);
				LcdLineString( 7, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
				sprintf(gszLine, " Tr2:%5d%5d%5d", gVout[VOUT_1].dwTr2, gVout[VOUT_2].dwTr2, gVout[VOUT_3].dwTr2);
				LcdLineString( 8, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
				sprintf(gszLine, " Vr2:%5d%5d%5d", gVout[VOUT_1].dwVr2, gVout[VOUT_2].dwVr2, gVout[VOUT_3].dwVr2);
				LcdLineString( 9, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
				sprintf(gszLine, " Tr3:%5d%5d%5d", gVout[VOUT_1].dwTr3, gVout[VOUT_2].dwTr3, gVout[VOUT_3].dwTr3);
				LcdLineString(10, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
				sprintf(gszLine, " Vr3:%5d%5d%5d", gVout[VOUT_1].dwVr3, gVout[VOUT_2].dwVr3, gVout[VOUT_3].dwVr3);
				LcdLineString(11, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
				sprintf(gszLine, " Tr4:%5d%5d%5d", gVout[VOUT_1].dwTr4, gVout[VOUT_2].dwTr4, gVout[VOUT_3].dwTr4);
				LcdLineString(12, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
				sprintf(gszLine, " Vr4:%5d%5d%5d", gVout[VOUT_1].dwVr4, gVout[VOUT_2].dwVr4, gVout[VOUT_3].dwVr4);
				LcdLineString(13, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
				sprintf(gszLine, " Tf1:%5d%5d%5d", gVout[VOUT_1].dwTf1, gVout[VOUT_2].dwTf1, gVout[VOUT_3].dwTf1);
				LcdLineString(14, LCD_ALIGN_LEFT, gszLine, COLOR_YELLOW, COLOR_BLACK);
			}

			_adc_ch = ADC_1;
			_adc_step = STEP_TOFF;
			_adc_temp = 0;
		}
	} else {
		pPktBuf[pktCnt++] = CHAR_CR;
	}
	//printf("-pPktBuf(%d) : %s\n", gvSysTickCount, pPktBuf);

	return pktCnt;
}

